﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ArduinoInterOp.Abstract;
using System.Net;
using System.IO;
using ArduinoInterOp.Delegates;
using System.Configuration;

namespace ArduinoInterOp
{
    public class ArduinoHTTPCommunication : IArduinoCommunication
    {
        private readonly string _uri;

        public ArduinoHTTPCommunication(string uri)
        {
            _uri = uri;
        }

        private HttpWebRequest GetRequest(string command)
        {
            var request = (HttpWebRequest) WebRequest.Create(_uri);

            request.Timeout = GetTimeout();

            var commandHeaderString = string.Format("!{0}@", command);

            request.Headers.Add("arduino", commandHeaderString);

            Arduino.DebugMessage("Command: " + commandHeaderString);

            return request;
        }

        private int GetTimeout()
        {
            var timeout = 5000;

            var configuradTimeout = ConfigurationManager.AppSettings["requestTimeout"];

            if (!string.IsNullOrEmpty(configuradTimeout) && int.TryParse(configuradTimeout, out timeout))
            { }

            return timeout;
        }

        public string SendSyncedCommand(string command)
        {
            var request = GetRequest(command);
           
            var response = request.GetResponse();

            return ReadResponse(response);
        }

        private static string ReadResponse(WebResponse response)
        {
            if (response != null)
            {
                using (var reader = new StreamReader(response.GetResponseStream()))
                {
                    var responseString = reader.ReadLine();

                    Arduino.DebugMessage("response: " + responseString);

                    return responseString.Trim();
                }
            }

            return null;
        }

        public event Delegates.ArsuinoResponseEventHandler Response;

        private class AsyncStateData
        {
            public WebRequest WebRequest { get; set; }
        }

        public void SendAsyncedCommand(string command)
        {
            var request = GetRequest(command);

            request.BeginGetResponse(ResponseAsyncCallback, new AsyncStateData(){ WebRequest = request});
        }

        private void ResponseAsyncCallback(IAsyncResult asyncResult)
        {
            var state = asyncResult.AsyncState as AsyncStateData;
            if (state == null) throw new ArgumentNullException("asyncResult");

            if(Response != null)
            {
               Response(this, new ArsuinoResponseEventArgs(ReadResponse(state.WebRequest.GetResponse()))); 
            }
        }

        public void ReadyCommandsMode()
        { }
    }
}
